from __future__ import annotations

import datetime as dt
import time
import hashlib
from typing import Any, Dict, List, Optional

from fastapi import APIRouter, Depends, Query
from pydantic import BaseModel, Field, root_validator
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from ..models import RunMode, AIAutoDecision
from ..services.ai_autotrader import (
    AIAutoTraderConfig,
    start_ai_trader,
    stop_ai_trader,
    list_ai_traders,
)
from ..db import get_session
from ..deps import require_admin


router = APIRouter(
    prefix="/ai/autotrader",
    tags=["ai-autotrader"],
    dependencies=[Depends(require_admin)],
)


def _generate_run_id(connector: str, trading_pair: str, account: str) -> str:
    ts = time.strftime("%Y%m%d-%H%M%S")
    raw = f"{connector}-{trading_pair}-{account}-{ts}"
    digest = hashlib.md5(raw.encode()).hexdigest()[:6]
    return f"ai-{connector}-{trading_pair}-{ts}-{digest}"


class StartAutoTraderReq(BaseModel):
    account_name: str = Field(..., description="账户名称，如 trader@example.com")
    connector_name: str = Field(
        ...,
        description="交易所简称或现货连接器，例如 gate / gate_io / okx；系统会自动推导永续连接器并为 AI 预先拉取 Gate K 线"
    )
    trading_pair: str = Field(..., description="交易对，如 BTC-USDT")
    max_notional_usd: float = Field(..., gt=0, description="最大名义金额（USD）")
    max_slippage_bps: int = Field(..., ge=0, description="最大滑点（基点）")
    max_daily_loss_usd: float = Field(..., ge=0, description="最大日亏损（USD）")
    mode: RunMode = Field(RunMode.shadow, description="运行模式：shadow|paper|live")
    interval_seconds: int = Field(120, ge=30, le=3600, description="循环执行间隔（秒），默认 120")
    loop_interval: Optional[int] = Field(None, alias="loop_interval", description="兼容旧字段，将写入 interval_seconds", exclude=True)
    run_id: Optional[str] = Field(None, description="自定义运行 ID，不填自动生成")

    @root_validator(pre=True)
    def _fill_interval_seconds(cls, values):
        if values.get("interval_seconds") is None:
            legacy = values.get("loop_interval")
            values["interval_seconds"] = legacy if legacy is not None else 120
        return values


class StopAutoTraderReq(BaseModel):
    run_id: str = Field(..., description="要停止的运行 ID")


class AIDecisionItem(BaseModel):
    id: int
    run_id: str
    ts: dt.datetime
    account_name: str
    connector_name: str
    trading_pair: str
    mode: RunMode
    prompt: str
    response_text: Optional[str] = None
    finish_reason: Optional[str] = None
    tool_invocations: Optional[List[Dict[str, Any]]] = None
    tokens_used: Optional[Dict[str, Any]] = None
    candles: Optional[List[Dict[str, Any]]] = None

    class Config:
        orm_mode = True


@router.post("/start")
async def start(req: StartAutoTraderReq) -> dict:
    run_id = req.run_id or _generate_run_id(req.connector_name, req.trading_pair, req.account_name)
    config = AIAutoTraderConfig(
        run_id=run_id,
        account_name=req.account_name,
        connector_name=req.connector_name,
        trading_pair=req.trading_pair,
        max_notional_usd=req.max_notional_usd,
        max_slippage_bps=req.max_slippage_bps,
        max_daily_loss_usd=req.max_daily_loss_usd,
        mode=req.mode,
        interval_seconds=req.interval_seconds,
    )

    await start_ai_trader(config)
    return {"status": "started", "run_id": run_id}


@router.post("/stop")
async def stop(req: StopAutoTraderReq) -> dict:
    await stop_ai_trader(req.run_id)
    return {"status": "stopped", "run_id": req.run_id}


@router.get("/list")
async def list_traders() -> dict:
    return {"items": list_ai_traders()}


@router.get("/decisions", response_model=List[AIDecisionItem])
async def list_decisions(
    run_id: Optional[str] = Query(None, description="运行 ID 过滤"),
    limit: int = Query(100, ge=1, le=500, description="返回条数，默认 100"),
    session: AsyncSession = Depends(get_session),
) -> List[AIDecisionItem]:
    stmt = select(AIAutoDecision).order_by(AIAutoDecision.ts.desc()).limit(limit)
    if run_id:
        stmt = stmt.where(AIAutoDecision.run_id == run_id)

    result = await session.execute(stmt)
    rows = result.scalars().all()
    return rows
